package com.simple.trade.service.vm.impl;

import com.google.common.base.Preconditions;
import com.simple.common.entity.ReqContext;
import com.simple.common.entity.ResData;
import com.simple.common.entity.constant.Payment;
import com.simple.common.entity.dto.pay.vm.CardInfo;
import com.simple.common.entity.dto.pay.vm.DirectPayDto;
import com.simple.common.entity.dto.pay.vm.DirectPayRspDto;
import com.simple.common.entity.dto.pay.vm.VmBaseDto;
import com.simple.common.entity.po.sys.ChannelComp;
import com.simple.common.entity.po.sys.Product;
import com.simple.common.entity.po.sys.Trade;
import com.simple.common.entity.req.vm.pay.DirectPayReqV2;
import com.simple.common.entity.req.vm.pay.PayBase;
import com.simple.common.utils.RSAUtil;
import com.simple.common.entity.vo.pay.DirectResV2;
import com.simple.trade.service.vm.DirectPayV2Service;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import java.net.URLEncoder;

/**
 * @author yasud
 * @date 2020年10月13日 14:04
 * @description
 */
@Service
public class DirectPayV2ServiceImpl extends PayBaseService<DirectResV2, DirectPayRspDto> implements DirectPayV2Service {

    @Value("${simple.publicKey}")
    String publicKey;

    /**
     * 直连支付2
     * @param req
     * @return
     */
    @Override
//    @Transactional(rollbackFor = Exception.class)
    public ResData<DirectResV2> directPayV2(DirectPayReqV2 req) {
        ResData<DirectResV2> res = pay(req, trade -> {
            trade.setCardHolder(req.getFirstName() + "_" + req.getLastName());
            trade.setCardExYear(Mono.fromCallable(()-> RSAUtil.encryptByPublicKey(req.getExpireYear(),publicKey)).block());
            trade.setCardExMonth(Mono.fromCallable(()->RSAUtil.encryptByPublicKey(req.getExpireMonth(),publicKey)).block());
            trade.setCardCvv(Mono.fromCallable(()->RSAUtil.encryptByPublicKey(req.getCvv(),publicKey)).block());
            trade.setCardNo(Mono.fromCallable(()->RSAUtil.encryptByPublicKey(req.getCardNo(),publicKey)).block());
            trade.setGoodsList(req.goodsListJson());
            trade.setBillingInfo(req.billingInfoJson());
            trade.setShippingInfo(req.shippingInfoJson());
        }, Payment.PAY_TYPE.VM_DIRECT_PAY_V2);
        return res;
    }

    @Override
    protected VmBaseDto getDto(Trade trade, ReqContext reqContext, PayBase payBase, ChannelComp channel, Product product) {
        DirectPayReqV2 v2 = (DirectPayReqV2) payBase;
        CardInfo cardInfo = CardInfo.builder()
                .cardFristName(v2.getFirstName())
                .cardLastName(v2.getLastName())
                .cardExMonth(v2.getExpireMonth())
                .cardExYear(v2.getExpireYear())
                .cardCvv(v2.getCvv())
                .cardNo(v2.getCardNo())
                .build();
        DirectPayDto directPayDto = DirectPayDto.generateDto(trade, reqContext, payBase.getExtraInfo(), channel, product,cardInfo);
        return directPayDto;
    }

    @Override
    @SneakyThrows
    protected DirectResV2 map(DirectPayRspDto rsp) {
        Trade trade = rsp.getTrade();
        Preconditions.checkNotNull(trade, "支付失败渠道服务错误，交易不能为空");
        DirectResV2 directResV2 = new DirectResV2();
        directResV2.setSerialNo(trade.getId());
        directResV2.setOrderNo(trade.getMerchantOrderNo());
        directResV2.setAmount(trade.getAmount());
        directResV2.setCurrency(trade.getCurrency());
        Preconditions.checkNotNull(rsp.getPayType(), "支付失败渠道服务错误，返回直连支付类型不能为空");
        directResV2.setPayType(rsp.getPayType());
        directResV2.setPayMsg(trade.getMsg());
        if (StringUtils.isNotBlank(rsp.getPayHtml())) {
            directResV2.setPayHtml(URLEncoder.encode(rsp.getPayHtml(), "UTF-8"));
        }
        else {
            directResV2.setPayHtml("");
        }
        if (StringUtils.isNotBlank(rsp.getPaymentUrl())) {
            directResV2.setPayUrl(URLEncoder.encode(rsp.getPaymentUrl(), "UTF-8"));
        }
        else {
            directResV2.setPayUrl("");
        }
        directResV2.setRemark(trade.getOrderDesc());
        directResV2.setPayStatus(trade.getStatus());
        return directResV2;
    }
}
